package com.alignet.gn.hibernate.dao;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.LockMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.alignet.gn.hibernate.TgnAction;
import com.alignet.gn.hibernate.TgnRole;
import com.alignet.gn.sesion.Container;
import com.alignet.gn.util.GNUtils;
import com.alignet.gn.util.Result;

/**
 * A data access object (DAO) providing persistence and search support for
 * TgnRole entities. Transaction control of the save(), update() and delete()
 * operations can directly support Spring container-managed transactions or they
 * can be augmented to handle user-managed Spring transactions. Each of these * methods provides additional information for how to configure it for the
 * desired type of transaction control.
 * 
 * @see com.alignet.gn.hibernate.TgnRole
 * @author MyEclipse Persistence Tools
 */

public class TgnRoleDAO extends HibernateDaoSupport {
    private static final Logger log = LoggerFactory.getLogger(TgnRoleDAO.class);

    protected void initDao() {
	// do nothing
    }

    public void save(TgnRole transientInstance) {
	log.debug("saving TgnRole instance");
	try {
	    getHibernateTemplate().save(transientInstance);
	    log.debug("save successful");
	} catch (RuntimeException re) {
	    log.error("save failed", re);
	    throw re;
	}
    }

    public void delete(TgnRole persistentInstance) {
	log.debug("deleting TgnRole instance");
	try {
	    getHibernateTemplate().delete(persistentInstance);
	    log.debug("delete successful");
	} catch (RuntimeException re) {
	    log.error("delete failed", re);
	    throw re;
	}
    }

    public TgnRole findById(java.lang.Integer id) {
	log.debug("getting TgnRole instance with id: " + id);
	try {
	    TgnRole instance = (TgnRole) getHibernateTemplate().get(
		    "com.alignet.gn.hibernate.TgnRole", id);
	    return instance;
	} catch (RuntimeException re) {
	    log.error("get failed", re);
	    throw re;
	}
    }

    public List<TgnRole> findByExample(TgnRole instance) {
	log.debug("finding TgnRole instance by example");
	try {
	    List<TgnRole> results = (List<TgnRole>) getHibernateTemplate()
		    .findByExample(instance);
	    log.debug("find by example successful, result size: "
		    + results.size());
	    return results;
	} catch (RuntimeException re) {
	    log.error("find by example failed", re);
	    throw re;
	}
    }

    public List findByProperty(String propertyName, Object value) {
	log.debug("finding TgnRole instance with property: " + propertyName
		+ ", value: " + value);
	try {
	    String queryString = "from TgnRole as model where model."
		    + propertyName + "= ?";
	    return getHibernateTemplate().find(queryString, value);
	} catch (RuntimeException re) {
	    log.error("find by property name failed", re);
	    throw re;
	}
    }

    public List findAll() {
	log.debug("finding all TgnRole instances");
	try {
	    String queryString = "from TgnRole";
	    return getHibernateTemplate().find(queryString);
	} catch (RuntimeException re) {
	    log.error("find all failed", re);
	    throw re;
	}
    }

    public TgnRole merge(TgnRole detachedInstance) {
	log.debug("merging TgnRole instance");
	try {
	    TgnRole result = (TgnRole) getHibernateTemplate().merge(
		    detachedInstance);
	    log.debug("merge successful");
	    return result;
	} catch (RuntimeException re) {
	    log.error("merge failed", re);
	    throw re;
	}
    }

    public void attachDirty(TgnRole instance) {
	log.debug("attaching dirty TgnRole instance");
	try {
	    getHibernateTemplate().saveOrUpdate(instance);
	    log.debug("attach successful");
	} catch (RuntimeException re) {
	    log.error("attach failed", re);
	    throw re;
	}
    }

    public void attachClean(TgnRole instance) {
	log.debug("attaching clean TgnRole instance");
	try {
	    getHibernateTemplate().lock(instance, LockMode.NONE);
	    log.debug("attach successful");
	} catch (RuntimeException re) {
	    log.error("attach failed", re);
	    throw re;
	}
    }

    public static TgnRoleDAO getFromApplicationContext(ApplicationContext ctx) {
	return (TgnRoleDAO) ctx.getBean("TgnRoleDAO");
    }
    
    public Result getActionsForSession(String rolValues, String total, boolean all, boolean state, Integer modulo){
    	log.info("Class: TgnRoleDAO - Method: getActionsForSession");
		Result result = new Result();
		List list = null;
		ArrayList vector = new ArrayList();
		String accept = "", denied = "";
		String rolValue = (rolValues == null || rolValues.length() == 0) ? "0" : rolValues;
		String[] todo = getIdActionsForSessionAD(rolValue, total, state);
		accept = todo[0];
		denied = todo[1];
		accept = (accept == null || accept.length() == 0) ? "-1" : accept;
		DetachedCriteria criteria = DetachedCriteria.forClass(TgnAction.class);
		if (denied.length() > 0) {
			criteria.add(Restrictions.sqlRestriction("IN_METHODCODE IN (" + denied + ")"));
		}
		criteria.addOrder(Order.asc("inIdaction"));
		list = (List) getHibernateTemplate().findByCriteria(criteria);
		log.info("Lista de acciones " + list.size());
		for (int i = 0; i < list.size(); i++) {
			TgnAction a = (TgnAction) list.get(i);
			vector.add(a);
		}
		// METODOS
		StringBuffer bf1 = new StringBuffer();
		ArrayList vMethod = new ArrayList();
	
		for (int i = 0; i < vector.size(); i++) {
			TgnAction bean = (TgnAction) vector.get(i);
			vMethod.add((bean.getVcMethod() != null && bean.getVcMethod().length() > 0) ? bean.getVcMethod().hashCode() + "" : "");
			bf1.append("{'ID':'" + bean.getInMethodcode() + "'},"); // JSON
		}
		if (vector.size() > 0) {
			bf1 = bf1.deleteCharAt(bf1.length() - 1).insert(0, "[").append("]");
		} else {
			bf1.append("[]");
		}
	
		// ===================================================
		// ACTIONS DENEGADOS
		StringBuffer bf2 = new StringBuffer();
		accept = (accept == null || accept.length() == 0) ? "-1" : accept;
		String[] array2 = accept.split(",");
		for (int i = 0; i < array2.length; i++) {
			bf2.append("{'ID':'" + array2[i] + "'},");
		}
	
		if (bf2.length() > 0) {
			bf2 = bf2.deleteCharAt(bf2.length() - 1).insert(0, "[").append("]");
		} else {
			bf2.append("[]");
		}
		/*************************************************************
		 * METODOS DE ROLES
		 **************************************************************/
		result.getVector().add(bf2.toString());
		result.getVector().add(vMethod);
		result.getVector().add(total);
		result.getVector().add(bf1.toString());
	
		return result;
	}

	public static String[] getIdActionsForSessionAD(String rolvalue, String totalactions, boolean state)  {
		log.info("Class: TgnRoleDAO - Method: getIdActionsForSessionAD");
		log.info("RolValue " + rolvalue);
		log.info("TotalActions  " + totalactions);
		String accept = "", denied = "";
		String[] todo = { "", "" };
		if (rolvalue == null || rolvalue.equalsIgnoreCase("0")) {
			return todo;
		}
		int total = Integer.parseInt(totalactions);
		BigInteger rolevalue = new BigInteger(rolvalue);
		String temp = rolevalue.toString(2);
		char[] bit = temp.toCharArray();
		for (int x = bit.length; x < total; x++) {
			temp = "0" + temp;
		}
		bit = temp.toCharArray();
		StringBuffer acep = new StringBuffer();
		StringBuffer denie = new StringBuffer();
		for (int x = bit.length - 1, y = 0; x >= 0; x--, y++) {
			if (bit[x] == '1') {
				acep.append("," + y +"");
			} else {
				denie.append("," + y+"");
			}
		}
		accept = acep.toString();
		denied = denie.toString();
		accept = accept.length() > 0 ? accept.substring(1) : "";
		denied = denied.length() > 0 ? denied.substring(1) : "";
		todo[0] = accept;
		todo[1] = denied;
		return todo;
	}

	public String getActionsTotalSQL(Integer module)  {
		log.info("Class: TgnRoleDAO - Method: getActionsTotalSQL");
		String result = "";
		String x = "select count(inMethodcode) from TgnAction";
		Long in = (Long) DataAccessUtils.uniqueResult(getHibernateTemplate().find(x));
		log.info("Total de Acciones " + in);
		if (in != null) {
			result = in.toString();
		}
		return result;
	}
	
	public List findByQuery(String queryString) {
		log.debug("findByQuery #1");
		return getHibernateTemplate().find(queryString);
	} 	
	public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) {
		log.debug("findByQuery #2");
		return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
	} 
	public List findByCriteria(DetachedCriteria criteria) {
		log.debug("findByQuery #2");
		return getHibernateTemplate().findByCriteria(criteria);
	} 
	
	public String updateRole(Integer id, Container cont){
		log.info("Class: TgnRoleDAO - Method: updateRole");
			Result result = getActionsForCreateRol("3");
			log.info("Trama " + result.getCadena());
			cont.setTramaCompleta(result.getCadena());
			
		return "success";
	}	
	
	

	
	public Result getActionsForCreateRol(String idModule) {
		String cadena = "";
		// actions de un rol
		Result result = getActionsRolForModule(idModule);
			if(result!=null){
				cadena = result.getCadena();
			}
			result = new Result();
			if(result!=null){
				result.setCadena(cadena);
			}
			return result;
		}
	
	public Result getActionsRolForModule(String idModule) {
		Result result = new Result();
		// todas las acciones para el modulo 3 (comercio) -- debe ser 1 para modulo emisor
		Result res=getActions(idModule);
		
		List vector = res.getVector();
		if(vector==null || vector.size()==0){
			result.setCadena("");
			return result; 
		}
		StringBuffer buff	 = new StringBuffer();
		StringBuffer buffT	 = new StringBuffer();
		String temp = "0";
				try {				
					for (int i = 0; i < vector.size(); i++) {
						TgnAction action = (TgnAction)vector.get(i);
							if(!action.getVcGroup().equals(temp)){
									if(buffT.length()>0){
										buff.append("{'E':'"+GNUtils.getMessage("com.object." + temp)+"','A':["+buffT.substring(0,buffT.length()-1)+"]},");
										buffT=new StringBuffer();
									}
								temp = action.getVcGroup();
							}
						buffT.append("{'M':'"+action.getVcDesc()+"','ID':'"+action.getInMethodcode()+"','P':'"+((action.getVcIdactionenabledbefore()==null)?"":action.getVcIdactionenabledbefore())+"'},");
							if((i+1)==vector.size())
							{
								buff.append("{'E':'"+GNUtils.getMessage("com.object." + temp)+"','A':["+buffT.substring(0,buffT.length()-1)+"]},");
							}	
					}
					result.setCadena("["+buff.substring(0,buff.length()-1)+"]");		
	//-------------------------------------------------------------------------------
				} catch (Exception e) {
					result.setCadena("");
				}

		return result;
	}
	
	private Result getActions(String idModule)  {
		Result result = new Result();
		ArrayList vector = new ArrayList();

		DetachedCriteria criteria = DetachedCriteria.forClass(TgnAction.class);
		criteria.add(Restrictions.ne("vcDesc", " "));
		criteria.addOrder(Order.asc("vcGroup"));

		List list = (List) getHibernateTemplate().findByCriteria(criteria);

		for (int i = 0; i < list.size(); i++) {
			TgnAction a = (TgnAction) list.get(i);
			vector.add(a);
		}

		result.setVector(vector);
		return result;

	}

	public void saveRol(TgnRole rol) {
		getHibernateTemplate().saveOrUpdate(rol);
	}	
	
	public String registraModificaRol(String cadena) {
		log.info("registraModificaRol");
		String rpta = "success";
		String actions = cadena;

		// ///////////Validacion de Predecesoras/////////////////////////////
		String[] xrol = actions.split(",");
		DetachedCriteria criteria = DetachedCriteria.forClass(TgnAction.class);
		criteria.add(Restrictions.sqlRestriction("IN_METHODCODE in(" + actions + ")"));
		List listRoles = (List) getHibernateTemplate().findByCriteria(criteria);
		String x = "";
		String action = "";
		Integer predecesora = 0;
		// Recorre todos las acciones encontradas para sacar las predecesoras
		log.info("Total de acciones a recorrer " + listRoles.size());
		for (int j = 0; j < listRoles.size(); j++) {
			TgnAction a = (TgnAction) listRoles.get(j);
			action = a.getVcDesc();
			log.info("Accion " + a.getVcDesc());
			String[] xpredc = a.getVcIdactionenabledbefore().split(",");
			if (xpredc.length > 0) {
				// Recorre todas las predecesoras de una accion
				for (int i = 0; i < xpredc.length; i++) {
					x = "0";
					// Recorre el arreglo de id's para verificar que se
					// encuentren las predecesoras
					for (int k = 0; k < xrol.length; k++) {
						if (xpredc[0].equals("")) {
							x = "1";
						} else {
							predecesora = Integer.parseInt(xpredc[i].trim());
						}
						if (xrol[k].equals(xpredc[i])) {

							x = "1";
						}
					}
					if (!x.equals("1")) {
						break;
					}
				}
				if (!x.equals("1")) {
					break;
				}
			}
		}
		
		DetachedCriteria criteria2 = DetachedCriteria.forClass(TgnAction.class);
		criteria2.add(Restrictions.eq("inMethodcode", predecesora));
		
		TgnAction ac = (TgnAction) DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(criteria2));
		if (!x.equals("1")) {
			rpta="lopcion," + action + "," + ac.getVcDesc();
			return rpta;
		}
		return rpta;
	}

	public void obtieneRol(TgnRole rol, Container container) {
		Result result = getActionsForCreateRol("3");
		container.setTramaCompleta(result.getCadena());
		roleEditInput(rol, container);
	}
	
	public String roleEditInput(TgnRole role, Container container)  {
		String actionsxedit = "";
		log.info("getVcGroupidaction " + role.getVcGroupidaction());
		log.info("getTotalActions " + container.getTotalActions());
		actionsxedit = role.getVcGroupidaction();
		if (actionsxedit != null && actionsxedit.trim().length() > 0 && !actionsxedit.equals("0")) {
			actionsxedit = getActionsForSession(role.getVcGroupidaction(), container.getTotalActions(), true, true, 3).getVector().get(0) + "";
		} else {
			actionsxedit = "[]";
		}
		container.setActionsxedit(actionsxedit);
		return actionsxedit;
	}

	public void update(TgnRole transientInstance) {
		log.debug("updating TgnRole instance");
		try {
		    getHibernateTemplate().save(transientInstance);
		    log.debug("update successful");
		} catch (RuntimeException re) {
		    log.error("update failed", re);
		    throw re;
		}
	}
}